<!--
 * Copyright © 2022 XXXXXXXXX
 * @Author: zhangxiang
 * @Date: 2022-08-22 17:57:38
 * @LastEditors: zhangxiang
 * @LastEditTime: 2023-09-21 15:20:47
 * @Description:
 *
-->

<template>
  <div class="service-split-ctn">
    <div class="apps">
      <!-- 筛选 -->
      <el-row type="flex" align="middle" class="top">
        <span class="name">应用名称</span>
        <el-input
          v-model="applicationName"
          style="width: 170px; margin-left: 10px; margin-right: 20px"
          size="small"
          class="input"
          placeholder="请输入应用名称"
          clearable
          @clear="clearNameClick"
          @keyup.enter.native="queryClick"
        />
        <span class="name">分类</span>
        <el-select
          v-model="category"
          placeholder="请选择应用分类"
          size="small"
          style="width: 170px; margin-left: 10px; margin-right: 20px"
        >
          <el-option
            v-for="item in categoryOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
        <el-button
          size="small"
          type="primary"
          @click="queryClick"
        >查询</el-button>
        <el-button size="small" @click="resetClick">重置</el-button>
      </el-row>
      <!-- 应用列表 -->
      <el-table
        ref="appsTable"
        v-loading="loading"
        class="apps-table app-common-table"
        :data="list"
        header-cell-class-name="listHeaderCell"
        :header-cell-style="{ color: '#696969' }"
        highlight-current-row
      >
        <el-table-column prop="name" label="应用名称" />
        <el-table-column prop="size" label="大小" />
        <el-table-column prop="category" label="分类" />
        <el-table-column prop="version" label="应用版本" />
        <el-table-column prop="provider" label="提供者" />
        <el-table-column prop="updateTime" label="更新时间" />
        <el-table-column label="操作" width="220">
          <template slot-scope="scope">
            <el-button
              v-if="scope.row.status >= 1"
              type="primary"
              size="mini"
              style="height: 22px; line-height: 22px; padding: 0 10px"
              @click="checkMicroServiceClick(scope.row)"
            >查看微服务</el-button>
            <el-button
              v-if="scope.row.status == 2"
              type="primary"
              size="mini"
              style="height: 22px; line-height: 22px; padding: 0 10px"
              @click="gotoCurrentStep(scope.row)"
            >跳转到当前状态</el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-row type="flex" justify="end" style="margin-top: 15px">
        <!-- 分页控制 -->
        <el-pagination
          background
          layout="total, prev, pager, next"
          :page-size="pageSize"
          :current-page.sync="pageNum"
          :total="totalSize"
          @current-change="changePage"
        />
      </el-row>
    </div>
    <template v-if="hasStartSplit || hasStartView">
      <!-- 拆解进度条 -->
      <div class="services">
        <div v-if="hasStartSplit" class="prog">
          <span>拆解进度</span>
          <el-progress
            style="width: 100%"
            :stroke-width="14"
            :percentage="splitPercent"
          />
        </div>
        <!-- 已拆解的微服务列表 -->
        <el-table
          v-loading="viewLoading"
          class="services-table app-common-table"
          :data="curServiceList"
          header-cell-class-name="listHeaderCell"
          :header-cell-style="{ color: '#696969' }"
        >
          <el-table-column prop="appName" label="应用名称" />
          <el-table-column prop="svcName" label="微服务名称" />
          <el-table-column prop="size" label="大小" />
          <el-table-column prop="provider" label="提供者" />
          <el-table-column prop="updateTime" label="更新时间" />
        </el-table>
      </div>
      <el-row type="flex" justify="end" style="margin-top: 30px">
        <el-button
          class="common-btn"
          type="primary"
          size="medium"
          :disabled="microServices.length == 0"
          @click="$emit('next-step', { appId: curAppId })"
        >下一步</el-button>
      </el-row>
    </template>
  </div>
</template>

<script>
import { APP_CATEGORYS } from '@/utils/cnap/constant'
import {
  getAppListSplit,
  getSplitProgress,
  getAppMicroService
} from '@/api/cnap/app-service'

const PROGRESS_INTERVAL = 1000 // 时间间隔

const STAGES_SPLIT = ['unzip', 'push']

export default {
  name: 'ServiceSplit',
  props: {
    // 拆解完成的微服务信息
    microServices: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      categoryOptions: APP_CATEGORYS, // 类别选项
      applicationName: '', // 应用名称
      category: '', // 类别
      loading: false, // 加载中
      pageSize: 5, // 页size
      pageNum: 1, // 页码
      totalSize: 0, // 总数
      list: [], // 列表
      hasStartSplit: false, // 是否启动微服务拆解
      splitPercent: 0, // 微服务拆解进度
      splitServices: [], // 拆解的微服务
      timerProgress: null, // 拆解进度查询计时器
      hasStartView: false, // 是否启动查看微服务
      viewLoading: false, // 查看微服务loading
      curAppId: '' // 当前应用id
    }
  },
  computed: {
    /**
     *
     * @description: 列表中展示的微服务信息
     * @return {*}
     *
     */
    curServiceList() {
      if (this.hasStartSplit) {
        return this.splitServices
      }
      if (this.hasStartView) {
        return this.microServices
      }
      return []
    }
  },
  created() {
    this.initPageData() // 初始化数据
  },
  destroyed() {
    if (this.timerProgress) {
      clearTimeout(this.timerProgress)
      this.timerProgress = null
    }
  },
  methods: {
    /**
     *
     * @description: 跳转到部署流程最新步骤
     * @return {*}
     *
     */
    gotoCurrentStep(row) {
      // 请求
      getAppMicroService(row.id).then((res) => {
        this.curAppId = row.id
        const microServices = Array.isArray(res.data) ? res.data : []
        // 是否全部微服务都添加了调度策略
        let scheduleStrategyAll = true
        // 是否全部微服务都添加了扩缩容策略
        let scaleStrategyAll = true
        microServices.forEach((element) => {
          const hasScheduleStrategy =
            element.scheduleStrategy && element.scheduleStrategy.id
          scheduleStrategyAll = scheduleStrategyAll && hasScheduleStrategy
          const hasScaleStrategy =
            Array.isArray(element.scaleStrategys) && element.scaleStrategys.length > 0
          scaleStrategyAll = scaleStrategyAll && hasScaleStrategy
        })
        this.$emit('update:microServices', microServices) // 更新微服务
        this.$emit('goto-step', {
          appId: this.curAppId,
          step: !scheduleStrategyAll ? 2 : 3 // 步骤跳转
        })
      })
    },
    /**
     *
     * @description: 是否处在流程中
     * @return {*}
     *
     */
    isInProcess() {
      if (this.hasStartView && this.viewLoading) {
        this.$message.warning({
          message: '正在查看微服务',
          duration: 1500
        })
        return true
      }
      if (this.hasStartSplit && this.timerProgress) {
        this.$message.warning({
          message: '正在拆解微服务',
          duration: 1500
        })
        return true
      }
      return false
    },
    /**
     *
     * @description: 获取应用相应的微服务信息
     * @param {*} appId
     * @return {*}
     *
     */
    getAppMicroServiceInfo(appId) {
      // 请求
      getAppMicroService(appId)
        .then((res) => {
          const microServices = Array.isArray(res.data) ? res.data : []
          this.$emit('update:microServices', microServices) // 更新微服务
          this.curAppId = appId
        })
        .finally(() => {
          this.viewLoading = false
        })
    },
    /**
     *
     * @description: 查看微服务列表
     * @param {*} row
     * @return {*}
     *
     */
    viewMicroServiceList(row) {
      if (this.isInProcess()) {
        // 查看中
        return
      }
      this.$refs.appsTable.setCurrentRow(row) // 选中当前行
      this.hasStartView = true
      this.hasStartSplit = false
      this.$emit('update:microServices', []) // 通过emit将已有微服务列表数据重置
      this.viewLoading = true
      this.getAppMicroServiceInfo(row.id)
    },
    /**
     * @description: 自动跳转下一步
     * @return {*}
     */
    autoNextStep(appId) {
      setTimeout(() => {
        this.$emit('next-step', { appId: appId }) // 下一步
      }, 1000)
    },
    /**
     *
     * @description: 获取拆解微服务进度
     * @param {*} appId
     * @return {*}
     *
     */
    getSplitProgressInfo(appId) {
      // 请求
      getSplitProgress(appId).then((res) => {
        if (res.data) {
          // 获取拆解数据
          // 拆解进度和已拆解的微服务
          this.splitPercent = STAGES_SPLIT.includes(res.data.stage)
            ? Math.min(100, Math.round(res.data.percent))
            : 0
          this.splitServices = Array.isArray(res.data.microServices)
            ? res.data.microServices
            : []
          if (this.splitPercent < 100) {
            // 没有拆解完成
            // 继续递归获取
            this.timerProgress = setTimeout(() => {
              this.getSplitProgressInfo(appId)
            }, PROGRESS_INTERVAL)
          } else {
            // 拆解完成
            // 清除timer
            if (this.timerProgress) {
              clearTimeout(this.timerProgress)
              this.timerProgress = null
            }
            this.$message.success({
              message: '微服务拆解完成',
              duration: 2000
            })
            this.getAppMicroServiceInfo(appId) // 更新微服务
            this.getAppList()
            setTimeout(() => {
              this.autoNextStep(appId) // 自动跳转下一步
            }, 1500)
          }
        }
      })
    },
    /**
     *
     * @description: 初始化拆解
     * @param {*} row
     * @return {*}
     *
     */
    initSplitApp(row) {
      // 请求拆解进度
      this.getSplitProgressInfo(row.id)
      // getSplitProgress(row.id).then((res) => {
      //   const stage = res.data.stage
      //   if (stage === 'split' || stage === 'push') {
      //     // 拆解中
      //     // 直接获取进度
      //     this.getSplitProgressInfo(row.id)
      //   } else {
      //     // 不在拆解中
      //     // 先进行拆解
      //     startSplitMicroService(row.id).then((res) => {
      //       this.getSplitProgressInfo(row.id)
      //     })
      //   }
      // })
    },
    /**
     *
     * @description: 拆解微服务
     * @param {*} row
     * @return {*}
     *
     */
    splitApp(row) {
      if (this.isInProcess()) {
        // 拆解中
        return
      }
      this.$refs.appsTable.setCurrentRow(row)
      this.hasStartSplit = true
      this.hasStartView = false
      this.$emit('update:microServices', []) // 通过emit将已有微服务列表数据重置
      this.splitServices = [] // 重置拆分数据
      this.splitPercent = 0
      this.initSplitApp(row)
    },
    /**
     * @description: 查看微服务
     * @param {*} row
     * @return {*}
     */
    checkMicroServiceClick(row) {
      // status 0-未上传应用包 1-已上传（自动化拆解） 2-已拆解、未完全部署 3-已部署
      if (row.status > 1) {
        // 查看微服务
        this.viewMicroServiceList(row)
      } else {
        // 拆解进度
        this.splitApp(row)
      }
    },
    /**
     *
     * @description: 切换页码
     * @param {*} pageNum
     * @return {*}
     *
     */
    changePage(pageNum) {
      this.pageNum = pageNum
      this.getAppList() // 请求数据
    },
    /**
     *
     * @description: 清除应用名称
     * @return {*}
     *
     */
    clearNameClick() {
      this.applicationName = ''
      this.pageNum = 1 // 第一页
      this.getAppList() // 请求数据
    },
    /**
     *
     * @description: 重置
     * @return {*}
     *
     */
    resetClick() {
      this.applicationName = ''
      this.category = ''
      this.pageNum = 1 // 第一页
      this.getAppList() // 请求数据
    },
    /**
     *
     * @description: 查询
     * @return {*}
     *
     */
    queryClick() {
      this.pageNum = 1 // 第一页
      this.getAppList() // 请求数据
    },
    /**
     *
     * @description: 获取分布式部署应用列表
     * @return {*}
     *
     */
    getAppList() {
      // 请求数据
      getAppListSplit({
        applicationName: this.applicationName,
        category: this.category,
        pageNum: this.pageNum,
        pageSize: this.pageSize
      })
        .then((res) => {
          if (res.data) {
            this.totalSize = res.data.totalSize
            this.list = Array.isArray(res.data.data) ? res.data.data : []
          } else {
            // 数据为空处理
            this.totalSize = 0
            this.list = []
          }
        })
        .finally(() => {
          this.loading = false
        })
    },
    /**
     *
     * @description: 初始化数据
     * @return {*}
     *
     */
    initPageData() {
      this.loading = true
      this.pageNum = 1 // 第一页
      this.getAppList() // 请求数据
    }
  }
}
</script>

<style lang="less" scoped>
@import "@/assets/css/common.less";
.service-split-ctn {
  .app-common-table {
    .el-table::before {
      background-color: #e9e9e9;
    }
    /deep/ .listHeaderCell {
      background: #f3f3f3;
      height: 40px;
      padding: 0;
      box-sizing: border-box;
      &:first-child {
        padding-left: 20px;
      }
    }

    /deep/ .el-table__body {
      .el-table__row td {
        height: 40px;
        padding: 0;
        &:first-child {
          padding-left: 20px;
        }
      }
    }
    /deep/ .el-table tbody tr:hover > .el-table__cell {
      background: #eaeaea;
    }
  }
  .apps {
    padding: 20px;
    box-sizing: border-box;
    background: #fdfdfd;
    border: 1px solid #ececec;

    .top {
      .name {
        .textStyle(14px , 400, #4a4a4a);
        line-height: 20px;
      }
    }

    .apps-table {
      margin-top: 20px;
    }
  }

  .services {
    margin-top: 20px;
    padding: 20px;
    box-sizing: border-box;
    background: #fdfdfd;
    border: 1px solid #ececec;

    .prog {
      display: flex;
      align-items: center;
      margin-bottom: 20px;

      span {
        .textStyle(14px , 400, #4a4a4a);
        line-height: 20px;
        margin-right: 15px;
        flex-shrink: 0;
      }
    }
  }
}
</style>
